home *** CD-ROM | disk | FTP | other *** search
- { --------------------------------------------------------------------------- }
- { DRVTYPES.PAS Drive type detection unit. Version 2.00 }
- { }
- { *** PUBLIC DOMAIN *** }
- { *** THERE ARE NO WARRANTIES PROVIDED AND AS-IS BASIS IS ASSUMED *** }
- { }
- { Initially written, placed in public domain, detection of Norton Diskreet }
- { and SuperStor drives in assembly language by Mr. Byte. }
- { Network drive detection fix, Stacker 4, DoubleDisk and }
- { Bernoully drive detection by Bobby Z. }
- { RAM drive detection by Janis Smits. }
- { Diskreet, SuperStor detection code donated by Vitaly Lysenko }
- { --------------------------------------------------------------------------- }
- { History:
-
- mid November, 1994 - initially released
- 29 November, 1994 - fixed network drive detection and added
- Stacker 4 drive detection
- 10 December, 1994 - added Janis's RAM drive detection method
- 16 January, 1995 - added Vertisoft DoubleDisk 2.6 drive detection
- 31 January, 1995 - added Bernoully drive detection
- 4 February, 1995 - added Norton Diskreet drive detection
- 5 February, 1995 - added SuperStor drive detection algo
- 6 February, 1995 - fixed bug with detection of CD-ROM drives,
- thanx to Ralf Quint
- 7 March, 1995 - released version 2. Mr. Byte made some
- modifications to the entire code
- }
- (**** General notes:
-
- This code can be easily ported to C/C++, because most of it is written in
- inline assembler. Just convert @@-style labels to __ and add "asm"s where
- needed. Note, that the call to checkStacker4 cannot be made in C/C++ the way
- it is done here (at least in Borland C++), you should do it like this:
-
- unsigned char GetDriveType( void )
- {
- register unsigned char temp;
- ...
- mov temp,Drive // passing the parameter
- }
- checkStacker4(temp);
- asm {
- ...
- }
-
- Warning: the entire code require 2048 stack space.
-
- end of General notes ****)
-
- {$S-,R-,I-,X+}
- { disable stack, I/O and range checking, enable extended syntax }
-
- unit DrvTypes;
- { drive types }
-
- interface
-
- const
- dtError = $00; { Invalid drive, letter not assigned }
- dtFixed = $01; { Fixed drive }
- dtRemovable = $02; { Removeable (floppy, etc.) drive }
- dtRemote = $03; { Remote (network) drive }
- dtCDROM = $04; { MSCDEX V2.00+ driven CD-ROM drive }
- dtDblSpace = $05; { DoubleSpace compressed drive }
- dtSUBST = $06; { SUBST'ed drive }
- { dudes, where are Stacker 1,2,3 check-routines? }
- dtStacker4 = $08; { Stacker 4 compressed drive }
- dtRAMDrive = $09; { RAM drive }
- dtDublDisk = $0A; { Vertisoft DoubleDisk 2.6 compressed drive }
- dtBernoully = $0B; { IOmega Bernoully drive }
- dtDiskreet = $0C; { Norton Diskreet drive }
- dtSuperStor = $0D; { SuperStor compressed drive }
-
- checkABforStacker : Boolean = False;
- { Controls whether we should check drives A: and B: for Stacker volumes.
- There is no convenient way to determine if drive is Stacker volume (like
- for DoubleSpace/Drive*Space volumes), so we should use absolute disk read
- function to do it. Drives A: and B: are typically floppy drives, thus one
- may not want to check them causing reads from floppies (which could be
- not inserted at all). /Bobby Z., 29/11/94 }
-
- function GetDriveType(Drive : byte) : byte;
- function CountValidDrives : byte;
-
- implementation
-
- type
- ControlBlk25 = record { control block for INT 25 extended call }
- StartSector : LongInt; { start sector to read }
- Count : Word; { number of sectors to read }
- BufferOffs : Word; { data buffer offset }
- BufferSeg : Word; { data buffer segment }
- end;
-
- function checkStacker4( Drive : Byte ) : Boolean; near; assembler;
- { returns True if Drive is Stacker 4 compressed volume, False otherwise.
- This also may return True with previous versions of Stacker - I didn't
- check it. /Bobby Z. 29/11/94 }
-
- var CB : ControlBlk25;
- Boot : array[1..512] of Byte;
- asm
- push ds
- mov al,Drive
- cmp checkABforStacker,1 { check A: & B: for Stacker volume? }
- jz @@1
- cmp al,1
- ja @@1
- sub al,al
- jmp @@Q
- @@1:
- push ss
- pop ds
- lea bx,CB
- sub ax,ax
- mov word ptr ds:ControlBlk25[bx].StartSector,ax
- mov word ptr ds:ControlBlk25[bx].StartSector[2],ax
- mov word ptr ds:ControlBlk25[bx].Count,1
- lea dx,Boot
- mov word ptr ds:ControlBlk25[bx].BufferOffs,dx
- mov word ptr ds:ControlBlk25[bx].BufferSeg,ds
- mov al,Drive
- sub cx,cx
- dec cx
- mov si,sp
- int 25h
- cli
- mov sp,si
- sti
- pushf
- lea si,Boot
- add si,1F0h { Stacker signature CD13CD14CD01CD03 should }
- sub al,al { appear at offset 1F0 of boot sector. }
- popf
- jc @@Q { was error reading boot sector - assume }
- { not Stacker drive }
- cmp word ptr ds:[si],13CDh
- jnz @@Q
- cmp word ptr ds:[si][2],14CDh
- jnz @@Q
- cmp word ptr ds:[si][4],01CDh
- jnz @@Q
- cmp word ptr ds:[si][6],03CDh
- jnz @@Q
- mov al,1
- @@Q:
- pop ds
- end; { checkStacker4 }
-
- function checkDiskreet(Drive : byte) : boolean; near; assembler;
- { Returns True if Drive is Norton Diskreet drive, otherwise it returns False }
- type
- TDiskreetPacket = record
- Header : array [1..6] of byte;
- Drive : char;
- Size : longint
- end;
- const DrvName : PChar = '@DSKREET'; {-Diskreet driver name}
- var Packet : TDiskreetPacket;
- asm
- push ds
- mov ax,0FE00h
- mov di,'NU' { 4E55h='NU' }
- mov si,'DC' { 4443h='DC' }
- int 2Fh
- or al,al { check for zero }
- je @@2
- cmp al,1 { check for 1 }
- je @@2
- @@1:
- sub al,al { return False }
- jmp @@4
- @@2:
- lds dx,DrvName
- mov ax,3D02h
- int 21h
- jc @@1
- mov bx,ax
- mov ax,seg [Packet]
- mov ds,ax
- mov dx,offset [Packet]
- mov es,ax
- mov di,dx
- mov cx,type TDiskreetPacket
- sub al,al
- cld
- rep stosb { initialize Packet fields }
- mov di,offset [Packet.Header]
- mov ax,12FFh { store first two bytes in Packet header }
- stosw
- mov di,offset [Packet.Drive]
- mov al,Drive
- add al,64 { convert drive number to drive letter }
- stosb { store drive letter }
- mov ax,4403h { ready to send Diskreet Packet }
- mov cx,7
- mov si,'dc' { 6463h = 'dc' }
- mov di,'NU' { 4E55h = 'NU' }
- int 21h { assuming ds=seg [Packet], dx=offset [Packet],
- bx=Handle }
- mov ah,3Eh
- int 21h { close device }
- mov si,offset [Packet.Size]
- lodsw
- or ax,ax
- jnz @@3
- lodsw
- or ax,ax
- jz @@1
- @@3:
- mov al,True { return True }
- @@4:
- pop ds
- end; { checkDiskreet }
-
- function checkSuperStor(Drive : byte) : boolean; near; assembler;
- type
- TSSPacket = record
- Sign : word;
- Sign1 : word;
- P : pointer;
- Res : array [1..4] of byte
- end;
- var
- Packet : TSSPacket;
- asm
- push ds
- mov ax,seg [Packet]
- mov es,ax
- mov di,offset [Packet]
- mov cx,type TSSPacket
- cld
- rep stosb { initialize SStor Packet structure }
- mov di,offset [Packet.Sign]
- mov ax,0AA55h
- stosw { init Packet.Sign }
- mov ax,0201h
- stosw { init Packet.Sign1 }
- mov ax,4404h
- mov dx,seg [Packet]
- mov ds,dx
- mov dx,offset [Packet]
- mov cx,12
- mov bl,Drive
- int 21h
- jc @@2 { if error then quit }
- mov si,offset [Packet.Sign]
- lodsw
- or ax,ax { if Packet.Sign<>0 then quit }
- jnz @@2
- lodsw
- cmp ax,0201h { if Packet.Sign1<>0201h then quit }
- jne @@2
- les di,[Packet.P]
- mov ax,[es:di+5Dh]
- test ax,40h { host drive? }
- jz @@2
- mov cl,byte ptr es:[di+24h]
- add cl,'A'
- mov ah,30h
- int 21h
- cmp ah,4
- jb @@1
- inc di
- @@1:
- les di,dword ptr es:[di+5Fh]
- mov bl,[es:di]
- add bl,'A'
- cmp cl,Drive { ????? I don't know whether bl or cl is a host
- SStor drive... }
- jne @@2
- mov al,True { return True }
- jmp @@3
- @@2:
- sub al,al { return False }
- @@3:
- pop ds
- end; { checkSuperStor }
-
- function GetDriveType; assembler;
- { Detects the type for a specified drive. Drive is a drive number to detect the
- type for (0=detect current (default) drive, 1=A, 2=B, 3=C...)
-
- Returns: One of the dtXXX-constants.
-
- Note: Function will work under DOS version 3.30 or later
- Also should work under DPMI and Windows.
- }
-
- asm
- cmp Drive,0
- jne @@1
- mov ah,19h { get active drive number in al }
- int 21h
- mov Drive,al
- inc Drive
- @@1:
- push word ptr [Drive]
- call checkDiskreet
- or al,al
- jz @CDROMcheck
- mov bl,dtDiskreet
- jmp @@7
- @CDROMcheck:
- mov ax,1500h { check for CD-ROM v2.00+ }
- sub bx,bx
- int 2Fh
- or bx,bx
- jz @@2
- mov ax,150Bh
- sub ch,ch
- mov cl,Drive
- dec cl { bug fixed with CD-ROM drives, thanx to Ralf Quint }
- int 2Fh { drives for this function start with 0 for A: }
- cmp bx,0ADADh
- jne @@2
- or ax,ax
- jz @@2
- mov bl,dtCDROM
- jmp @@7
- @@2:
- mov ax,4409h { check for SUBST'ed drive }
- mov bl,Drive
- int 21h
- jc @DblSpaceChk
- test dh,80h
- jz @DblSpaceChk
- mov bl,dtSUBST
- jmp @@7
- @DblSpaceChk:
- mov ax,4A11h { check for DoubleSpace drive }
- mov bx,1
- mov dl,Drive
- dec dl
- int 2Fh
- or ax,ax { is DoubleSpace loaded? }
- jnz @@3
- cmp dl,bl { if a host drive equal to compressed, then get out... }
- je @@3
- test bl,80h { bit 7=1: DL=compressed,BL=host
- =0: DL=host,BL=compressed }
- jz @SStorChk { so avoid host drives, assume host=fixed :) }
- inc dl
- cmp Drive,dl
- jne @SStorChk
- mov bl,dtDblSpace
- jmp @@7
- @SStorChk:
- push word ptr [Drive]
- call checkSuperStor
- or al,al
- jz @@3
- mov bl,dtSuperStor
- jmp @@7
- @@3:
- mov ax,4409h { check for remote drive }
- mov bl,Drive
- int 21h
- jc @@5
- and dh,10h
- jz @@4
- mov bl,dtRemote
- jmp @@7
- @@4:
- mov al,Drive { check for Stacker 4 volume }
- or al,al
- jz @@getDrv
- dec al
- @@goStac:
- push ax
- call checkStacker4
- or al,al
- jz @@8
- mov bl,dtStacker4
- jmp @@7
- @@8:
- mov ax,4408h { check for fixed (hard) drive }
- mov bl,Drive
- int 21h
- jc @@5
- or al,al
- jz @@6
- push ds { check for RAM drive }
- mov ax,ss
- mov ds,ax
- mov si,sp
- sub sp,28h { allocate 28h bytes on stack }
- mov dx,sp
- mov ax,440Dh { generic IOCTL }
- mov cx,860h { get device parameters }
- int 21h { RAMDrive and VDISK don't support this command }
- jc @@cleanup
- pushf
- mov di,dx
- cmp byte ptr ds:[di+6],0F8h { DoubleDisk returns 0F8h in media type}
- jz @@dubldsk { field of BPB if drive in question is }
- { compressed }
- popf
- jmp @@cleanup
- @@dubldsk:
- popf
- mov bl,dtDublDisk
- mov sp,si
- pop ds
- jmp @@7
- @@cleanup:
- mov sp,si
- pop ds
- mov bl,dtRAMDrive
- jc @@7
- push ds
- mov ah,1Ch { this function works _really_ slowly }
- mov dl,Drive { get media descriptor pointer }
- int 21h
- cmp byte ptr ds:[bx],0FDh
- pop ds
- jnz @@fixed
- push ds
- mov ah,32h { get BPB pointer }
- mov dl,Drive
- int 21h
- cmp byte ptr ds:[bx+0Bh],2 { Sectors per FAT is more than 2 for }
- pop ds { Bernoully drives }
- jz @@fixed
- mov bl,dtBernoully
- jmp @@7
- @@fixed:
- mov bl,dtFixed
- jmp @@7
- @@5:
- sub bl,bl { mov bl,dtError cuz dtError=0 }
- jmp @@7
- @@getDrv:
- mov ah,19h
- int 21h
- jmp @@goStac
- @@6:
- mov bl,dtRemovable { else - removeable media }
- @@7:
- mov al,bl
- end; { GetDriveType }
-
- function CountValidDrives; assembler;
- { - returns number of assigned letters in system }
- var Drive, Count : byte;
- asm
- mov Drive,1
- mov Count,0
- @@1:
- push word ptr Drive
- call GetDriveType
- or al,dtError
- jz @@2
- inc Count
- @@2:
- inc Drive
- cmp Drive,26
- jbe @@1
- mov al,Count
- end;
-
- end.
-